/*
 * ========THE SOLMIX PROJECT=====================================
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.gnu.org/licenses/ 
 * or see the FSF site: http://www.fsf.org. 
 */

package org.solmix.fmk.i18n;

import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.solmix.SLXConstants;
import org.solmix.fmk.util.MessageTools;

/**
 * The <code>ResourceBundleCache</code> caches resource bundles per OSGI bundle.
 * 
 * @author Administrator
 * @version $Id$ 2011-3-15
 */
@SuppressWarnings( "unchecked" )
public class ResourceBundleCache
{

   private Map resourceBundleEntries;

   private final Bundle bundle;

   private final Map resourceBundles;



   public ResourceBundleCache()
   {
      this( null );
   }

   public ResourceBundleCache( Bundle bundle )
   {
      this.bundle = bundle;
      this.resourceBundles = new HashMap();
   }

   ResourceBundle getResourceBundle( Locale locale )
   {
      if ( locale == null )
      {
         return getResourceBundleInternal( MessageTools.DEFAULT_LOCALE );
      }
      return getResourceBundleInternal( locale );
   }

   ResourceBundle getResourceBundleInternal( Locale locale )
   {

      if ( locale == null )
      {
         return null;
      }
      synchronized ( resourceBundles )
      {
         ResourceBundle bundle = (ResourceBundle) resourceBundles.get( locale );
         if ( bundle != null )
         {
            return bundle;
         }
      }
      ResourceBundle parent = getResourceBundleInternal( getParentLocale( locale ) );
      ResourceBundle bundle = loadResourceBundle( parent, locale );
      synchronized ( resourceBundles )
      {
         resourceBundles.put( locale, bundle );
      }
      return bundle;
   }

   /**
    * @param parent
    * @param locale
    * @return
    */
   private ResourceBundle loadResourceBundle( ResourceBundle parent, Locale locale )
   {
      String path = "_" + locale.toString();
      final URL source = (URL) getResourceBundleEntries().get( path );
      return new PropertyResourceBundle( parent, source );
   }

   /**
    * @return
    */
   private synchronized Map getResourceBundleEntries()
   {
      HashMap _resourceBundleEntries = new HashMap();
      int start = 0;
      if ( SLXConstants.isOSGI() )
      {

      }

      if ( this.resourceBundleEntries == null )
      {
         String _file = null;
         if ( SLXConstants.isOSGI() && bundle != null )
         {
            _file = (String) bundle.getHeaders().get( Constants.BUNDLE_LOCALIZATION );

         }
         if ( _file == null )
         {
            _file = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
         }

         if ( _file.startsWith( "/" ) )
         {
            _file = _file.substring( 1 );
         }
         int slash = _file.lastIndexOf( '/' );
         String fileName = _file.substring( slash + 1 );
         String path = ( slash <= 0 ) ? "/" : _file.substring( 0, slash );
         Enumeration locales = null;
         if ( SLXConstants.isOSGI() && bundle != null )
         {
            locales = bundle.findEntries( path, fileName + "*.properties", false );
         } else
         {
            String _rootPath = getClass().getResource( "/" ).getPath();
            locales = getLocalEntries("CLASSPATH:" + path, fileName + "*.properties", false);
         }
         if ( locales != null )
         {
            while ( locales.hasMoreElements() )
            {
               URL entry = (URL) locales.nextElement();
               String entryPath = entry.getPath();
               if ( SLXConstants.isOSGI() && bundle != null )
               {
                  start = 1 + _file.length();
               } else
               {
                  start = entryPath.lastIndexOf( fileName ) + fileName.length();
               }
               final int end = entryPath.length() - 11;
               entryPath = entryPath.substring( start, end );

               if ( entryPath.length() == 0 )
               {
                  entryPath = "_" + MessageTools.DEFAULT_LOCALE.toString();
               }

               if ( !_resourceBundleEntries.containsKey( entryPath ) )
               {
                  _resourceBundleEntries.put( entryPath, entry );
               }
            }
         }// END (locales != null)
         this.resourceBundleEntries = _resourceBundleEntries;
      }// END (this.resourceBundleEntries == null)
      return this.resourceBundleEntries;
   }

   /**
    * @param path
    * @param string
    * @param b
    * @return
    */
   protected Enumeration getLocalEntries( String path, String filePattern, boolean b )
   {
      Object sm = System.getSecurityManager();
      if ( sm != null )
      {
         // TODO deal security
      }
      Enumeration localEnum = new FilterEnumeration(path, filePattern, false);
      return localEnum;
   }

   /**
    * @param locale
    * @return
    */
   private Locale getParentLocale( Locale locale )
   {
      if ( locale.getVariant().length() != 0 )
      {
         return new Locale( locale.getLanguage(), locale.getCountry() );
      } else if ( locale.getCountry().length() != 0 )
      {
         return new Locale( locale.getLanguage(), "" );
      }
      // no parent
      return null;
   }
}
